<?php
declare (strict_types = 1);

namespace app\controller\frontend;

use app\BaseController as AppBaseController;
use app\model\Theme;
use app\model\VisitLog;
use app\model\Website;
use app\service\ApiService;
use think\facade\Cache;
use think\facade\View;

class BaseController extends AppBaseController
{
    protected $rootDomain;
    protected $domain;
    protected $siteId;
    protected $sellerId;
    protected $theme;
    protected $lang;
    protected $viewBase;
    protected $settingData;
    protected $parentSiteId;
    protected $realSiteId;
    protected $viewSiteId;
    protected $preview;

    /**
     * @throws \app\exception\ModelException
     * @throws \Exception
     */
    public function initialize()
    {
        $this->setCommonParam();
        $this->getRootDomain();
        $this->setRealSiteId();
        $this->getActiveTheme();
        $this->setVisitedData();
        parent::initialize();
    }

    /**
     * @throws \app\exception\ModelException
     */
    public function setCommonParam()
    {
        // 更新版本标识
        updateVersion();
        $domain = $this->request->host();
        $Website = new Website();
        $website = $Website->getWebsiteByDomain($domain,'id,domain,seller_id,parent_id,status')['data'];

        if ($website['status'] == 2) {
            $this->to404();
        }

        // 是否为预览状态
        $historyViewTime = session('history-view');
        $preview = $this->request->param('preview', '');
        if (!empty($preview)) {
            if ((time() - $historyViewTime) < 30 * 60) {
                // 30分钟内可预览
                $this->preview = 1;
            } else {
                header('Location: /');
                return;
            }
        }

        $this->domain = $domain;
        $this->siteId = $website['id'];
        $this->parentSiteId = $website['parent_id'];
        $this->sellerId = $website['seller_id'];
        $this->lang = $this->setLang();
        $this->viewBase = config('view.view_dir_name');
        define('INDEX_SITE_ID',$this->siteId);
        define('INDEX_SELLER_ID',$this->sellerId);
        define('INDEX_LANG',$this->lang);
    }

    public function getRootDomain()
    {
        $rootDomain = $this->request->rootDomain();
        if( $rootDomain === 'com.cn'){
            $domainArr = explode('.',$this->domain);
            array_shift($domainArr);
            $this->rootDomain = implode('.',$domainArr);
        }else{
            $this->rootDomain = $rootDomain;
        }
    }

    /**
     * @throws \app\exception\ModelException
     * @throws \app\exception\ModelEmptyException
     */
    public function getActiveTheme()
    {
        $Theme = new Theme();
        $theme = $Theme->getActiveTheme(['seller_id'=>$this->sellerId,'website_id'=>$this->viewSiteId,'lang'=>$this->lang,'is_active'=>1])['data']->toArray();
        $cacheKey = $this->sellerId .'_'.$this->siteId .'_'. $this->lang . '_website_cache_key';
        $settingData = Cache::get($cacheKey);
        if(empty($settingData)){
            $settingData = ApiService::setWebsiteSetting($this->sellerId,$this->siteId,$this->lang);
        }
        $this->settingData = $settingData;

        if(isMobile() && !empty($settingData['common_template']) && $settingData['common_template'] == 2){
            $this->theme = 'm_' . $theme['theme'];
        }else{
            $this->theme = $theme['theme'];
        }
    }

    public function setRealSiteId()
    {
        $siteId = $this->siteId;
        $Theme = new Theme();
        $theme = $Theme->getActiveTheme(['seller_id'=>$this->sellerId,'website_id'=>$siteId,'lang'=>$this->lang,'is_active'=>1])['data'];
        $this->viewSiteId = $siteId;

        // 本站点没有安装启用模板，页面加载用父级的模板
        if ($this->parentSiteId && empty($theme)){
            $this->viewSiteId = $this->parentSiteId;
        }

        if($this->parentSiteId){
            $siteId = $this->parentSiteId;
        }
        define('INDEX_REAL_SITE_ID',$siteId);
        return $this->realSiteId = $siteId;
    }

    public function setLang(): string
    {
        $baseUrl = trim($this->request->baseUrl(),'/');
        $firstPath = explode('/',$baseUrl)[0];
        $langArr = config('system.lang');
        if(empty($firstPath) || !in_array($firstPath,$langArr)){
            $firstPath = config('lang.default_lang');
        }
        return $firstPath;
    }

    protected function assign($name,$value = ''): \think\View
    {
        return View::assign($name, $value);
    }

    /**
     * 加载模板输出
     * @access protected
     * @param string $template 模板文件名
     * @param array $vars     模板输出变量
     * @return mixed
     */
    protected function fetch(string $template = '', array $vars = [])
    {
        $template = $this->parseTemplate($template);
        $this->_initializeView($this->viewSiteId,$this->lang,$this->theme);

        $html = View::fetch($template, $vars);
        $replace = <<<EOL
<script id="baseJs" src="/system_file/js/base.min.js"></script>
</head>
EOL;
        $html = str_replace('</head>', $replace, $html);
        return $html;
    }

    /**
     * 加载模板输出(system_file)
     * @access protected
     * @param string $template 模板文件名
     * @param array $vars     模板输出变量
     * @return mixed
     */
    protected function fetchSystem(string $template = '', array $vars = [])
    {
        $template = $this->parseTemplateSystem($template);
        $this->_initializeViewSystem($this->viewSiteId,$this->lang,$this->theme);

        $html = View::fetch($template, $vars);
        $replace = <<<EOL
<script id="baseJs" src="/system_file/js/base.min.js"></script>
</head>
EOL;
        $html = str_replace('</head>', $replace, $html);
        return $html;
    }

    /**
     * 定位模板
     * @param $template
     * @return string
     */
    private function parseTemplate($template): string
    {
        $path = CMS_ROOT . $this->viewBase . DIRECTORY_SEPARATOR . $this->viewSiteId.DIRECTORY_SEPARATOR .$this->lang.DIRECTORY_SEPARATOR.$this->theme;

        if (!empty($this->preview)) {
            $path = CMS_ROOT . 'public/themes/preview/'.$this->theme;
        }

        $ext = getFileExt($template);
        $path .= DIRECTORY_SEPARATOR . ltrim($template,'/');
        if( $ext != config('view.view_suffix')){
            $path .= '.'.config('view.view_suffix');
        }
        return $path ;
    }

    /**
     * 定位模板
     * @param $template
     * @return string
     */
    private function parseTemplateSystem($template): string
    {
        $path = CMS_ROOT . 'public/system_file' . DIRECTORY_SEPARATOR;
        $ext = getFileExt($template);
        $path .= DIRECTORY_SEPARATOR . ltrim($template,'/');
        if( $ext != config('view.view_suffix')){
            $path .= '.'.config('view.view_suffix');
        }
        return $path ;
    }

    /**
     * 常量替换
     * @param $siteId
     * @param $lang
     * @param $themeName
     */
    protected function _initializeView($siteId,$lang,$themeName)
    {
        if (!empty($this->preview)) {
            $viewReplaceStr = [
                '__TMPL__'     => "/themes/preview/{$themeName}",
                '__STATIC__'   => empty($this->settingData['static_file']) ? "/themes/preview/{$themeName}/static" : $this->settingData['static_file'] ,
            ];

            View::engine()->config([
                'view_path' => CMS_ROOT . '/public/themes/preview/' .$this->theme . '/',
                'tpl_replace_string' => $viewReplaceStr,
                'display_cache' => false,
                'tpl_cache' => false,
            ]);
        } else {
            $viewReplaceStr = [
                '__TMPL__'     => "/themes/website/{$siteId}/{$lang}/{$themeName}",
                '__STATIC__'   => empty($this->settingData['static_file']) ? "/themes/website/{$siteId}/{$lang}/{$themeName}/static" : $this->settingData['static_file'] ,
            ];
            View::engine()->config([
                'view_path' => CMS_ROOT . $this->viewBase . DIRECTORY_SEPARATOR . $siteId. DIRECTORY_SEPARATOR .$this->lang.DIRECTORY_SEPARATOR.$this->theme .DIRECTORY_SEPARATOR,
                'tpl_replace_string' => $viewReplaceStr,
                'display_cache' => false,
                'tpl_cache' => false,
            ]);
        }
    }

    /**
     * 常量替换
     * @param $siteId
     * @param $lang
     * @param $themeName
     */
    protected function _initializeViewSystem($siteId,$lang,$themeName)
    {
        $viewReplaceStr = [
            '__TMPL__'     => "/themes/website/{$siteId}/{$lang}/{$themeName}",
            '__STATIC__'   => empty($this->settingData['static_file']) ? "/themes/website/{$siteId}/{$lang}/{$themeName}/static" : $this->settingData['static_file'] ,
        ];

        View::engine()->config([
            'view_path' => CMS_ROOT . 'public/system_file' . DIRECTORY_SEPARATOR,
            'tpl_replace_string' => $viewReplaceStr,
            'display_cache' => false,
            'tpl_cache' => false,
        ]);
    }

    /**
     * @throws \Exception
     */
    private function setVisitedData()
    {
        $VisitLog = new VisitLog();
        $ip = request()->ip();
        $agent = !empty(request()->header()['user-agent']) ? request()->header()['user-agent'] : '未知设备';
        $address = getLocationByIp($ip,2);
        if(empty($address['province'])){
            $area = "内网ip";
        }else{
            $area = $address['province']."-".$address['city'];
        }
        $url = $this->request->domain().$this->request->url();
        $device = getDeviceInfo($agent);
        $param = [
            'seller_id' => $this->sellerId,
            'website_id' => $this->siteId,
            'domain' => $this->domain,
            'referrer' => empty($_SERVER['HTTP_REFERER']) ? '未知' : $_SERVER['HTTP_REFERER'],
            'url' => $url,
            'ip' => $ip,
            'agent' => $agent,
            'visited_area' => $area,
            'visited_device' => $device['deviceOs'] .'/'.$device['deviceVersion'],
            'visited_time'  => date('Y-m-d',time())
        ];

        $VisitLog -> addCustomData($param);
    }

    public function to404()
    {
        header('Location: /system_file/hc_error/404.html');
        exit();
    }
}
